package mylibrary.io.nio.nonBlock.sample1;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Iterator;

public class Server implements Runnable{

	private int port1 = 8099;
	private int port2 = 9099;
	
	private ServerSocketChannel serverSocket1;
	private ServerSocketChannel serverSocket2;
	
	private SocketChannel clientChannel1;
	private SocketChannel clientChannel2;
	
	private ByteBuffer buff = ByteBuffer.allocate(512);
	
	private Selector selector;
	
	public Server() {
		init();
	}
	
	public void init() {
		try {
			this.selector = SelectorProvider.provider().openSelector();
			
			this.serverSocket1 = ServerSocketChannel.open();
			this.serverSocket1.configureBlocking(false);
			this.serverSocket1.socket().bind(new InetSocketAddress("localhost", this.port1));
			this.serverSocket1.register(selector, SelectionKey.OP_ACCEPT);
			

			this.serverSocket2 = ServerSocketChannel.open();
			this.serverSocket2.configureBlocking(false);
			this.serverSocket2.socket().bind(new InetSocketAddress("localhost", this.port2));
			this.serverSocket2.register(selector, SelectionKey.OP_ACCEPT);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void accept(SelectionKey key) throws IOException {
		ServerSocketChannel server = (ServerSocketChannel) key.channel();
		
		if(server.equals(serverSocket1)) {
			clientChannel1 = server.accept();
			clientChannel1.configureBlocking(false);
			
			clientChannel1.register(this.selector, SelectionKey.OP_READ);
		} else {
			clientChannel2 = server.accept();
			clientChannel2.configureBlocking(false);
			
			clientChannel2.register(selector, SelectionKey.OP_READ);
		}
	}
	
	public void read(SelectionKey key) throws IOException {
		this.buff.clear();
		
		SocketChannel channel = (SocketChannel) key.channel();
		
		int count = channel.read(this.buff);
		
		if (count == -1) {
			key.channel().close();
			key.cancel();
			return;
		}
		
		String input = new String(this.buff.array()).trim();
		if(channel.equals(this.clientChannel1)) {
			System.out.println("This is A");
			System.out.println(input);
		} else {
			System.out.println("This is B");
			System.out.println(input);
		}
	}
	
	public void run() {
		
		while(true) {
			try {
				
				this.selector.select();	
				
				Iterator selectorKeys = this.selector.selectedKeys().iterator();
				while(selectorKeys.hasNext()) {
					
					SelectionKey key = (SelectionKey) selectorKeys.next();
					selectorKeys.remove();
					
					if(!key.isValid()) {
						continue;
					}
					
					if(key.isAcceptable()) {
						this.accept(key);
					} else if(key.isReadable()) {
						this.read(key);
					}
				}
				
			}catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		Server server = new Server();
		Thread thread = new Thread(server);
		thread.start();
	}

}
